#pragma once
#include<assert.h>
#include<time.h>


template<class K, class V>
struct AVLTreeNode
{
	pair<K, V> _kv;
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;

	int _bf;  // balance factor

	AVLTreeNode(const pair<K, V>& kv)
		:_kv(kv)
		, _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _bf(0)
	{}
};

template<class K,class V>
struct AVLTree
{
	typedef AVLTreeNode<K, V>Node;
public:
	bool Insert(const pair<K, V>& kv)//迭代+更新平衡因子
	{
		//空树
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}
		//准备迭代建立关系
		Node* parent = nullptr;
		Node* cur = _root;
		//寻找在哪里插入
		while (cur)
		{
			if (cur->_kv.first < kv.first)//节点值小于插入值 大的往右走说明这里的不够满足胃口
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;//值相等 不要 避免冗余
			}
		}

		cur = new Node(kv);//嘎嘎插入

		//建立联系
		if (parent->_kv.first < kv.first)
		{
			parent->_right = cur;
			cur->_parent = parent;//如果是普通的二叉搜索树没有这句
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		//更新平衡因子
		while (parent)//最多更新到根
		{
			// 新增在右，parent->bf++;
			// 新增在左，parent->bf--;
			if (cur == parent->_left)
			{
				parent->_bf--;
			}
			else
			{
				parent->_bf++;
			}


			//是否继续更新的条件 见笔记
			if (parent->_bf == 0)
			{
				break;
			}
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				//反着来 往上走
				cur = parent;
				parent = parent->_parent;
			}
			else if (parent->_bf == 2 || parent->_bf == -2)
			{
				if (parent->_bf == 2 && cur->_bf == 1)
				{
					RotateL(parent);//RR 在较高右子树插入右节点
				}
				else if (parent->_bf == -2 && cur->_bf == -1)
				{
					RotateR(parent);//LL 在较高的左子树插入左节点
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					RotateLR(parent);//LR  在较高的左子树插入右节点
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					RotateRL(parent);// RL 在较高的右子树插入左节点
				}
				else
				{
					assert(false);
				}
                break;
			}
			else
			{
				assert(false);//如果这里报错 说明插入写的有问题 可以更快的判断错误位置
			}
		}
		return true;
	}
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;//30的右孩子60记录
		Node* subRL = subR->_left;//记录可能不存在的b

		//开始旋转
		parent->_right = subRL;//60的左调整到30的右
		if (subRL)//如果b存在的话 要是不存在 空指针也没有parent
			subR->_parent = parent;

		Node* ppNode = parent->_parent;//担心是局部子树 记录下根节点的parent

		subR->_left = parent;//30到60的左边
		parent->_parent = subR;//parent节点一定存在 所以不写if语句

		//如果非局部子树 根节点的parent得置空
		if (ppNode == nullptr)
		{
			_root = subR;//subR就是60
			_root->_parent == nullptr;//必须得置空
		}
		//如果是局部子树 
		else
		{
			if (ppNode->_left == parent)//不会改变 parent可是我一开始就传进来的参数
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
			subR->_parent = ppNode;//相呼应 保持一致
		}
		parent->_bf = subR->_bf = 0;//只动了60 和 30的孩子 没有动abc
	}
	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}

		Node* ppNode = parent->_parent;
		subL->_right = parent;
		parent->_parent = subL;

		//if (_root == parent)
		if (ppNode == nullptr)
		{
			_root = subL;
			_root->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}

			subL->_parent = ppNode;
		}

		subL->_bf = parent->_bf = 0;
	}
	void RotateLR(Node* parent)
	{
		Node* subL = parent->_left;//30
		Node* subLR = subL->_right;//60
		int bf = subLR->_bf;//用60衡量平衡因子
		//先对30进行左旋
		RotateL(parent->_left);
		//对根进行右旋
		RotateR(parent);
		//平衡因子的调整
		if (bf == -1) // subLR左子树新增
		{
			subL->_bf = 0;
			parent->_bf = 1;
			subLR->_bf = 0;
		}
		else if (bf == 1) // subLR右子树新增
		{
			parent->_bf = 0;
			subL->_bf = -1;
			subLR->_bf = 0;
		}
		else if (bf == 0) // subLR自己就是新增
		{
			parent->_bf = 0;
			subL->_bf = 0;
			subLR->_bf = 0;
		}
		else
		{
			assert(false);//方便调整代码
		}
	}
	void RotateRL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		int bf = subRL->_bf;
		RotateR(parent->_right);
		RotateL(parent);
		if (bf == -1)//subRL左树新增
		{
			parent->_bf = 0;
			subRL->_bf = 0;
			subR->_bf = 1;
		}
		else if (bf == 1)
		{
			parent->_bf = -1;
			subRL->_bf = 0;
			subR->_bf = 0;
		}
		else if (bf == 0)
		{
			parent->_bf = 0;
			subRL->_bf = 0;
			subR->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

	//方便测试 所以写了这些函数
	void Inorder()
	{
		_Inorder(_root);
	}

	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;

		_Inorder(root->_left);
		cout << root->_kv.first << ":" << root->_kv.second << endl;
		_Inorder(root->_right);
	}

	int Height(Node* root)
	{
		if (root == nullptr)
			return 0;

		int lh = Height(root->_left);
		int rh = Height(root->_right);

		return lh > rh ? lh + 1 : rh + 1;
	}

	bool IsBalance()
	{
		return IsBalance(_root);
	}

	bool IsBalance(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}

		int leftHeight = Height(root->_left);
		int rightHeight = Height(root->_right);

		if (rightHeight - leftHeight != root->_bf)
		{
			cout << root->_kv.first << "平衡因子异常" << endl;
			return false;
		}

		return abs(rightHeight - leftHeight) < 2
			&& IsBalance(root->_left)
			&& IsBalance(root->_right);
	}

private:
	Node* _root = nullptr;
};
void TestAVLTree()
{
	//int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
	//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
	AVLTree<int, int> t;
	for (auto e : a)
	{
		t.Insert(make_pair(e, e));
	}

	t.Inorder();

	cout << t.IsBalance() << endl;
}